import io
from datetime import date, datetime
from typing import List, Union, Optional, Dict
import struct
import peewee
from emi.bar.data import Interval
from emi.bar.storage.model import BaseDBModel
from emi.core.DBSource import DBSource
from emi.trade.data import PositionData, Direction, Offset,OpType
from emi.io import write_float_compress, read_float_compress, write_int_compress, read_int_compress, write_str_list, \
    read_str_list

# symbol: str
# direction: Direction
# update: datetime = None
# create: datetime = None
# volume_frozen: float = 0  ## 被冻结的持仓
# volume_available: float = 0  ## 可用仓位
# price_in: float = 0  ## 买入价格，多次买入会摊薄价格
# duration: int = 0  ## 持有天数
# price_cur: float = 0  ## 每股现价

class PositionDataModel(BaseDBModel):

    symbol:str = peewee.CharField(primary_key=True,max_length=64)
    direction:str = peewee.CharField(max_length=32)
    update:datetime = peewee.TimestampField(index=True)
    create:datetime = peewee.TimestampField(index=True)

    volume_frozen: float = peewee.DoubleField(null=False)
    volume_available: float = peewee.DoubleField(null=False)
    price_in: float = peewee.DoubleField(null=False)
    price_cur: float = peewee.DoubleField(null=False)
    duration: int = peewee.IntegerField(null=False)

    is_long:bool = peewee.BooleanField(index=True)

    def to_dict(self):
        return self.__data__

    @staticmethod
    def from_data(bar: PositionData,is_long:bool):
        model = PositionDataModel()
        model.symbol = bar.symbol
        model.direction = bar.direction.value
        model.update = bar.update
        model.create = bar.create
        model.volume_frozen = bar.volume_frozen
        model.volume_available = bar.volume_available
        model.price_in = bar.price_in
        model.price_cur = bar.price_cur
        model.duration = bar.duration
        model.is_long = is_long
        return model

    def to_bar(self) -> PositionData:
        bar = PositionData(
            symbol=self.symbol,
            direction=Direction(self.direction),
            update=self.update,
            create=self.create,
            volume_frozen=self.volume_frozen,
            volume_available=self.volume_available,
            price_in=self.price_in,
            price_cur=self.price_cur,
            duration=self.duration,
        )
        return bar


class PositionDataStorage:

    def __init__(self, source: DBSource, table_name=None):
        # indexes_desc = (
        #     (("dimen_value", "interval", "datetime"), True),
        # )
        if table_name is None:
            table_name = 't_position'
        self.source = source.init_peewee(table_name, PositionDataModel, indexes=None, ignore_inited=True)

    def save_bars(self, bars: List[PositionData],is_long:bool):
        """
        保存Bar数据。
        """
        ds = [PositionDataModel.from_data(i,is_long) for i in bars]
        with self.source.use_peewee() as db_model:
            db_model.save_all(ds)


    def size(self) -> int:
        with self.source.use_peewee() as db_model:
            return db_model.select().count()

    def clear(self):
        with self.source.use_peewee() as db_model:
            db_model.drop_table()
            db_model.create_table()

    def get_all(self,is_long:bool) -> List[PositionData]:
        """
        返回指定日期的量化数据。
        :param dimen:
        :param interval:
        :param tag:
        :return:
        """
        with self.source.use_peewee() as db_model:
            s = db_model.select().where(db_model.is_long == is_long)
            if s:
                return [db_bar.to_bar() for db_bar in s]
        return []
